
#include "stdio.h"
#include "stdint.h"
#include "math.h"
#include "nh_spo2.h"
#include "data.h"
#include "stdlib.h"
#include "string.h"
#include "test_sig_gen.h"

#include "log_lib/log.h"

#define BUFF_SIZE 8




uint32_t  buff_RED[BUFF_SIZE] = {10,8,6,3,5,7,9,11};
uint16_t  rise_trend_cnt = 0; // 上升趋势计数
uint16_t  fall_trend_cnt = 0; // 下降趋势计数

#include "nh_spo2.h"
#include "nh_base_alg.h"
#include "assit_func.h"

void time_tick_test(void);

void gravity_gen_test(void);

int32_t time_valid_check(uint16_t *list_a,uint16_t len_a);

void time_valid_check_test(void);

spo2_result_t reslt;


typedef struct 
{
  uint16_t res_info[10];
  uint16_t tick_info[10];
  uint8_t  _len;
  uint8_t  index;
}diff_lim_t;

void     diff_lim_init(diff_lim_t *tick_info);
uint16_t diff_step_limit(diff_lim_t *tick_info,uint16_t new_input);



void diff_lim_test(void);


int main()
{
    spo2_init();
    // int32_t ret=0;
    uint8_t buff_cnt=0;
    // uint8_t peak_cnt=0;
    // uint8_t valley_cnt=0;
    uint16_t time_s=10;
    double fs=1.0;
    uint16_t HR = 80;
    fs = (double)HR/60.0;
    int32_t x[500];
    int32_t x2[500];
    double val;
    double VAL[500];
    double set_r = 0.6;
    double ir_ac_pi = 0.04;
    double red_ac_pi = ir_ac_pi*set_r;
    
    printf("RED PI %f\tIR PI %f\n",red_ac_pi,ir_ac_pi);
    const double phase_diff = (0/180.0)*3.1415926;


    log_set_level(LOG_INFO);


    // FILE *fp = fopen("./spo2_log.txt","w");
    // log_add_fp(fp,LOG_INFO);

    log_info("---Raw Start---\n");

    // fclose(fp);


    for(int i=0;i<(50*time_s);i++)
    {
        // val = sin(fs*2.0*3.1415926*i/50);
// ((2*(sin(f*t)+0.6*sin(2*f*t+0.18*pi)))+5)*200+5000;

        val = 2.0*sin(fs*2.0*3.1415926*i/50.0f) ; // + 1.3*sin((2.0*fs*2.0*3.1415926*i/50.0f)+0.19*(3.1415926));

        VAL[i]=(sin(2.3*fs*2.0*3.1415926*i/50)+2.5)*50;
        int32_t val_sim_ir = (int32_t)((val+1.1)*(8000))+10000;

        //// 生成测试信号  RED
        x[i]    = (int32_t)((val+2.0)*300000.0*red_ac_pi)+300000.0*(1-red_ac_pi);
        
        //// 生成测试信号  IR
        // val = sin(phase_diff+(fs*2.0*3.1415926*i)/50);
        x2[i]   = (int32_t)((val+2.0)*300000.0*ir_ac_pi)+300000.0*(1-ir_ac_pi);
        buff_cnt++;

        // buff_cnt%=10;
        // if(buff_cnt==0)
        // {
        //     printf("\n");
        // }
        // printf("%4.6f , %6d,%6d\n",val,x[i],x2[i]);
    }
    printf("---Raw End---\n");
    
    //  测试算法输出
    // for(uint16_t index=0;index<50*time_s;index++)
    // {
    //     spo2_input(x[index],x2[index]);
    //     reslt = output_spo2_result();
    //     printf("[%d] { IR:%9d\tRED:%9d } -> HR:[%3d]\tSpO2:[%.3f]\n",index,x2[index],x[index],reslt.hr,reslt.spo2);
    // }
    // uint32_t syep = 0;
    // test_sig_gen_hr_dy(hr_list,_hr_len,&syep);

    /// 测试 系数生成
    // float coffval=0.0f;
    // for(uint16_t i=1;i<200;i++)
    // {
    //     coffval = diff_coffient_gen((float)(i));
    //     printf("spo2 %d\tcvoff: %.3f\n",i,coffval);
    // }

/**
    常温俊澍B2中指.csv
    常温俊澍B2食指.csv
    常温俊澍B3中指.csv
    常温俊澍B3食指.csv
    常温俊澍B4中指.csv
    常温俊澍B4食指.csv
    常温曾诚B2食指 - 副本.csv
    常温曾诚B2食指.csv
    常温曾诚B3食指.csv
    常温曾诚B4食指.csv
**/    
 ///" C:\Users\zhangzhi\Downloads\指夹式demo性能测试(对标鱼跃)-240514-LJS\常温俊澍B3中指.csv"


/**  2024-05-14
 * 
        常温俊澍B2中指.csv cc
        常温俊澍B2食指.csv  cc
        常温俊澍B3中指.csv  cc
        常温俊澍B3食指.csv  cc
        常温俊澍B4中指.csv  cc
        常温俊澍B4食指.csv  cc
        常温张智B2食指.csv  cc
        常温张智B3食指.csv  cc
        常温张智B4食指.csv  cc
        常温文赣B2食指.csv  cc
        常温文赣B3食指-1.csv
        常温文赣B4食指.csv
*/


/**   C:\Users\zhangzhi\Downloads\指夹式demo性能测试(对标鱼跃)-240516-LJS
     
        常温俊澍B2中指.csv
        常温俊澍B3中指.csv
        常温俊澍B4中指.csv
        常温张智B2食指.csv
        常温张智B3食指.csv
        常温张智B4食指.csv
        常温文赣B2食指.csv
        常温文赣B3食指.csv
        常温文赣B4食指.csv
        常温若兰B2中指.csv
        常温若兰B3中指.csv
        常温若兰B4中指.csv
        常温隆燕B2中指.csv
        常温隆燕B3中指.csv
        常温隆燕B4中指.csv
**/
    time_valid_check_test();

    diff_lim_test();

#if 1
/**
 C:/Users/zhangzhi/Downloads/指夹式demo性能测试(对标鱼跃)-240523-LJS/

    ├─常温俊澍B2中指/常温俊澍B2中指.csv
    ├─常温俊澍B3中指/常温俊澍B3中指.csv
    ├─常温俊澍B4中指/常温俊澍B4中指.csv
    ├─常温文桦B2中指/常温文桦B2中指.csv
    ├─常温文桦B3中指/常温文桦B3中指.csv
    ├─常温文桦B4中指/常温文桦B4中指.csv
    ├─常温文赣B2中指/常温文赣B2中指.csv
    ├─常温文赣B3中指/常温文赣B3中指.csv
    └─常温文赣B4中指/常温文赣B4中指.csv
 */


    /// "C:\Users\zhangzhi\Downloads\指夹式demo性能测试(对标鱼跃)-240523-LJS\常温俊澍B2中指\常温俊澍B2中指.csv"
    char line[1024];
    // char *base_path = "/mnt/c/Users/zhangzhi/Downloads/指夹式demo性能测试(对标鱼跃)-240523-LJS/";
    char *base_path = "/mnt/c/Users/zhangzhi/Downloads/指夹式demo性能测试(对标鱼跃)-240530-LJS-back1/指夹式demo性能测试(对标鱼跃)-240530-LJS/";
    // char *file_path [9]={    
    // "常温俊澍B2中指/常温俊澍B2中指.csv",
    // "常温俊澍B3中指/常温俊澍B3中指.csv",
    // "常温俊澍B4中指/常温俊澍B4中指.csv",
    // "常温文桦B2中指/常温文桦B2中指.csv",
    // "常温文桦B3中指/常温文桦B3中指.csv",
    // "常温文桦B4中指/常温文桦B4中指.csv",
    // "常温文赣B2中指/常温文赣B2中指.csv",
    // "常温文赣B3中指/常温文赣B3中指.csv",
    // "常温文赣B4中指/常温文赣B4中指.csv",};
    char *file_path [15]={
        // "常温俊澍B2中指.csv",
        // "常温俊澍B3中指.csv",
        // "常温俊澍B4中指.csv",
        // "常温张智B2食指.csv",
        // "常温张智B3食指.csv",
        // "常温张智B4食指.csv",
        // "常温文赣B2食指.csv",
        // "常温文赣B3食指.csv",
        // "常温文赣B4食指.csv",
        // "常温若兰B2中指.csv",
        // "常温若兰B3中指.csv",
        // "常温若兰B4中指.csv",
        // "常温隆燕B2中指.csv",
        // "常温隆燕B3中指.csv",
        // "常温隆燕B4中指.csv"
        
"常温俊澍B2食指-动态后静坐/常温俊澍B2食指-动态后静坐.csv",
"常温俊澍B3食指-动态后静坐/常温俊澍B3食指-动态后静坐.csv",
"常温俊澍B4食指-动态后静坐/常温俊澍B4食指-动态后静坐.csv"
        
        };



    /// 新的字符串  路径
    char file_all_path[1024]; 
   char folderName[50];
    char resultPath[300];
     char resultPath_all[300];
    
    for (int i = 0; i < 3; i++) {
        
        strcpy(file_all_path, base_path);
        strcat(file_all_path, file_path[i]); //// 数据文件路径
        

        sscanf(file_path[i], "%[^.]", folderName);

        // 在文件夹名称后面添加"-Result.csv"
        sprintf(resultPath, "%s-Result-0531.csv", folderName);
        sprintf(resultPath_all, "%s%s",base_path,resultPath);

        printf("[%2d]-> %s\n",i,file_all_path);
        
        printf("       %s\n", resultPath_all);
#if 1

///  "C:\Users\zhangzhi\Downloads\指夹式demo性能测试(对标鱼跃)-240530-LJS\常温俊澍B2食指-动态后静坐\常温俊澍B2食指-动态后静坐.csv"
    // FILE *file = fopen("/mnt/c/Users/zhangzhi/Downloads/指夹式demo性能测试(对标鱼跃)-240530-LJS/常温俊澍B3食指-动态后静坐/常温俊澍B3食指-动态后静坐.csv", "r");
    
    FILE *file = fopen(file_all_path, "r");
    if (file == NULL) {
        printf("无法打开文件\n");
        return 1;
    }
    fgets(line, sizeof(line), file); //// 跳过1行


    // freopen("/mnt/c/Users/zhangzhi/Downloads/指夹式demo性能测试(对标鱼跃)-240530-LJS/常温俊澍B3食指-动态后静坐/常温俊澍B3食指-动态后静坐-Result-0531-3.csv", "w", stdout);

    freopen(resultPath_all,"w", stdout);
 
    printf("RED,IR,None,ALG_HR,ALG_SPO2,ALG_R,REC_HR,REC_SPO2,REC_R\n");

    double data[7];
    int count = 0;
    float r = 0.0f;
    while (fscanf(file, "%lf,%lf,%lf,%lf,%lf,%lf", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5]) != EOF) {
        count++;
        // for (int i = 0; i < 2; i++) {
        //     printf("%d ", (int)data[i]);
        // }
        spo2_input((int)data[1],(int)data[0]); /// 输入数据  red,ir
        reslt = output_spo2_result();
        r = get_spo2_r_val();
        // printf("*[%d] { IR:%9d\tRED:%9d } -> HR:[%3d]\tSpO2:[%.3f] [%f]\t",count,(int)data[0],(int)data[1],reslt.hr,reslt.spo2,r);
        // printf("| %d , %lf , %lf|\n",(int)data[3],data[4],data[5]);

        //  RED,IR,ALG_HR,ALG_SPO2,ALG_R,REC_HR,REC_SPO2,REC_R
        printf("%d,%d,1999,%d,%.4lf,%.4lf,%d,%.4lf,%.4lf\n",(int)data[1],(int)data[0],reslt.hr,reslt.spo2,r,(int)data[3],data[4],data[5]);
    }
    fclose(stdout);
    printf("数组长度： %d\n", count);
    fclose(file);    
#endif
    }
#endif


    // float val_uint16[10] ={2.0f,5.0f,8.0f,10.0f,12.0f,18.0f,22.0f,30.0f,55.0f,1.0f}; 
    // InsertionSort_float(val_uint16,10 );
    // for(uint16_t ix=0;ix<10;ix++)
    // {
    //     printf("%f\n",val_uint16[ix]);
    // }

    // double xnt[4] = {4,34,66,94}; // 已知的x值
    // double ynt[4] = {80000,86000,84000,81000}; // 已知的y值，即f(x[i])的值
    // double xvalnt = 42; // 要插值的x值

    // double yval = newton_interpolate(xnt, ynt, 4, xvalnt);
    // printf("Newton's interpolation at x = %f is %f\n", xvalnt, yval);


    // float xx[4] = {4,34,66,94}; // 已知的x值
    // float yx[4] = {80000,86000,84000,81000}; // 已知的y值
    // float x_val = 42; // 要插值的x值
    // float divided_diff[4]; // 存储差分的数组

    // // 计算差分
    // compute_divided_differences(xx, yx, divided_diff, 4);

    // // 进行插值
    // float y_val;
    // for(uint16_t ix=0;ix<95;ix++)
    // {
    //     y_val = newton_divide_diff_interpolate(xx, divided_diff, (float)ix, 4);
    //     printf("%d , %d\n",ix,(int32_t)(y_val+0.5));
    // }
    // printf("Interpolated value at x = %f is %f\n", x_val, y_val);

    //// 牛顿重心法拟合
    // int32_t xx[4] = {4,34,66,94}; // 已知的x值
    // int32_t yx[4] = {80000,86000,84000,81000}; // 已知的y值
    // int32_t yval=0;

    // for(uint16_t i=0;i<67;i+=2)
    // {
    //     yval = fitval(xx,yx,3,i);
    //     printf("%d , %d\n",i,yval);
    // }

    



    // uint16_t  va_loc=0;
    // int32_t  peak_loc_val[14];
    // if(peak_cnt==4) /// de trend degree 2
    // {
    //     for(va_loc=0;va_loc<peak_cnt;va_loc++) /// for valley value
    //     {
    //         peak_loc_val[va_loc] = -1*raw_ppg[peak_right[va_loc]];
    //         xloc[va_loc] = (float)peak_right[va_loc];
    //         yval[va_loc] = (float)peak_loc_val[va_loc];
    //         printf("%d , %d\t%f,%f\n",peak_right[va_loc],peak_loc_val[va_loc],xloc[va_loc],yval[va_loc]);
    //     }
    //     // for(uint16_t index=0;index<raw_ppg_len;index++) //// 生成基线并去除
    //     // {
    //     //    base_line_shadow[index]=fitval(peak_loc_val,peak_loc,3,index);
    //     //    printf("%d , %d\n",index,base_line_shadow[index]);
    //     // }
    //     float divided_diff[4]; // 存储差分的数组
    //     compute_divided_differences(xloc, yval, divided_diff, 4);
    //     float base_val = 0.0;
    //     base_val = -1*raw_ppg[peak_right[0]];
    //     printf("base_val %f\n",base_val);
    //     float vhorzon_cop = 0.0f;
    //     for(uint16_t index=0;index<raw_ppg_len;index++) //// 生成基线并去除
    //     {
    //         base_line_shadow[index]=newton_divide_diff_interpolate(xloc,divided_diff,(float)index,4) ;
    //         vhorzon_cop = base_val - base_line_shadow[index];
    //         printf("%d , %f ,%f,%d\n",index,base_line_shadow[index], -1.0f*(float)raw_ppg[index]+vhorzon_cop,-1*raw_ppg[index]);
    //     }   
    // }
    // else if (peak_cnt>3 && peak_cnt<14 ) /// de trend degree 3
    // {
        

    // }else /// No peak ,No de trend or unvalid
    // {


    // }

    ///    time_tick_test();

    // gravity_gen_test();

// time_valid_check_test();
    /// peak right
    // for (uint32_t i = 0; i < peak_cnt; i++)
    // {
    //     printf("%d ",peak_right[i]);
    // }
    // printf("\n");
    // printf("peak cnt %d\n",peak_cnt);
    // }
    return 0;
}


// void compute_divided_differences(float x[4], float y[4], float table[4], int n) 
// {
//     for (int j = 0; j < n; j++) {
//         table[j] = y[j];
//     }

//     for (int i = 1; i < n; i++) {
//         for (int j = n - 1; j >= i; j--) {
//             table[j] = (table[j] - table[j - 1]) / (x[j] - x[j - i]);
//         }
//     }
// }

// // 牛顿重心多项式插值
// float newton_divide_diff_interpolate(float x[4], float divided_diff[4], float x_val, int n) 
// {
//     float result = divided_diff[n - 1];
//     for (int i = n - 2; i >= 0; i--) {
//         result = divided_diff[i] + (x_val - x[i]) * result;
//     }
//     return result;
// }


void time_tick_test(void)
{
    // spo2_time_tick_t handle;
    // time_tick_init(&handle, 100);
    // uint16_t mean_val;
    // float    mean_spo2;
    // for(uint32_t i=1;i<250;i++)
    // {   
    //     printf("-->[%d]-->\n",i);
    //     if(i%10==0)
    //     {
    //         time_tick_save_hr(&handle,i);
    //         time_tick_save(&handle,i);
    //         mean_val = mean_value_uint16(handle.hr_timeRes,handle.hr_tick_size);
    //         mean_spo2 = mean_value_float(handle.spo2,handle.tick_size);
            
    //         for(uint16_t i=0;i<handle.tick_size;i++)
    //         {
    //             printf("%f\t",handle.spo2[i]);
    //         }
    //         printf("\n");
    //         for(uint16_t i=0; i<handle.hr_tick_size;i++)
    //         {
    //             printf("%d\t",handle.hr_timeRes[i]);
    //         }
    //         printf("\n");
    //         printf("mean_val %d mean_spo2 %f\n",mean_val,mean_spo2);
    //     }
    //     time_ticks_update_tick(&handle);
    // }
}


void gravity_gen_test(void)
{

    uint16_t test_raw[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}; 
    uint16_t res=0;

    res = mean_value_uint16_Weighted(test_raw,sizeof(test_raw)/sizeof(test_raw[0]));
    printf("gravity_gen_test res %d\n",res);
}




void time_valid_check_test(void)
{
    uint16_t lista []={ 29 ,31,30, 63 ,29, 30, 92 };
    uint16_t mean_value=0xffff;

    /// print raw
    printf("raw: %ld\n", sizeof(lista)/sizeof(lista[0]) );
    for(uint16_t i=0;i<sizeof(lista)/sizeof(lista[0]);i++ )
    {
        printf("%d\t",lista[i]);
    }
    printf("\n");



    int32_t all_valid = time_valid_check(lista, sizeof(lista)/sizeof(lista[0]));
    printf("all_valid %d\n",all_valid);
    for(uint16_t i=0;i<sizeof(lista)/sizeof(lista[0]);i++ )
    {
        printf("%d\t",lista[i]);
        /// zero check
        if (lista[i]!=0)
        {
            mean_value +=lista[i];
        }
    }
    printf("\n");
    /// calc mean 
    mean_value = (uint16_t)(((float)mean_value/(float)all_valid)+0.5);
    printf("mean_value %d\n",mean_value);

}




/**
算法需求：
给定的数据和缓冲区，限制变化的强度
typedef struct 
{
  uint16_t res_info[10];
  uint16_t tick_info[10];
  uint8_t  _len;
  uint8_t  index;
};
 */


void diff_lim_init(diff_lim_t *tick_info)
{
    tick_info->_len = 10;
    tick_info->index = 0;
}

uint16_t diff_step_limit(diff_lim_t *tick_info,uint16_t new_input)
{

    return 0;
}


/// @brief 限制变化，每秒2bpm
// const float diff_lim_s = 2.0f;
const float sample_freq = 50.0f;




void diff_lim_test(void)
{
uint32_t tick_tick [10] = {322,295,268,242,213,170,128, 86, 29,  1};
uint16_t tick_res[10]   = { 80, 81, 81, 71, 64, 60, 57, 55, 55, 54};

uint16_t next = diff_lim(tick_res,tick_tick,sizeof(tick_res)/sizeof(tick_res[0]),2.0f,50.0f);
printf("next %d\n",next);


uint32_t tick_tick1 [10] = {322,295,268,242,213,170,128, 86, 29,  1};
uint16_t tick_res1[10]   = { 54, 55, 55, 57, 60, 64, 71, 81, 81, 80};
 next = diff_lim(tick_res1,tick_tick1,sizeof(tick_res1)/sizeof(tick_res1[0]),3.0f,50.0f);
printf("next %d\n",next);




}





